package com.ruoyi.common.utils.ocr;

import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.util.encoders.Hex;

import java.math.BigInteger;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

public class SM2Decryption {
    private static final String DEFAULT_PRIVATE_KEY_HEX = "7CD211C74C9413101BB1DF06A846E2A38451A0F4D03E8D868E8B034DC9F137AF";
    private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

    private final ECPrivateKeyParameters privateKeyParams;
    private final int mode; // 0-C1C2C3, 1-C1C3C2

    public SM2Decryption(int mode, String PRIVATE_KEY_HEX) throws Exception {
        this.mode = mode;

        // 初始化SM2曲线参数
        ECNamedCurveParameterSpec sm2Spec = ECNamedCurveTable.getParameterSpec("sm2p256v1");

        // 将十六进制私钥转换为BigInteger
        BigInteger privateKey = new BigInteger(PRIVATE_KEY_HEX, 16);

        // 创建ECDomainParameters
        ECDomainParameters domainParams = new ECDomainParameters(
            sm2Spec.getCurve(),
            sm2Spec.getG(),
            sm2Spec.getN(),
            sm2Spec.getH()
        );

        // 创建私钥参数
        this.privateKeyParams = new ECPrivateKeyParameters(privateKey, domainParams);
    }

    public SM2Decryption() throws Exception {
        this(0, DEFAULT_PRIVATE_KEY_HEX); // 默认使用C1C2C3模式
    }

    public String sm2Decrypt(String hexCiphertext, Charset charset) {
        try {

            if (!hexCiphertext.startsWith("04")) {
                hexCiphertext = "04" + hexCiphertext;
            }

            // 将十六进制密文转换为字节数组
            byte[] ciphertext = Hex.decode(hexCiphertext);

            // 创建SM2引擎并设置模式
            SM2Engine.Mode sm2Mode = (mode == 0) ? SM2Engine.Mode.C1C2C3 : SM2Engine.Mode.C1C3C2;
            SM2Engine sm2Engine = new SM2Engine(sm2Mode);

            // 初始化解密模式：直接使用ECPrivateKeyParameters，而不是ParametersWithRandom
            // 注意：解密时通常不需要随机数源，加密时才需要。
            sm2Engine.init(false, privateKeyParams); // 关键修改：直接传递私钥参数

            // 执行解密
            byte[] decryptedBytes = sm2Engine.processBlock(ciphertext, 0, ciphertext.length);

            // 尝试将解密后的字节转换为字符串
            try {
                return new String(decryptedBytes, charset);
            } catch (Exception e) {
                // 如果包含非文本内容，直接返回字节的十六进制表示
                return Hex.toHexString(decryptedBytes);
            }
        } catch (Exception e) {
            throw new RuntimeException("SM2解密失败", e);
        }
    }

    public String sm2Decrypt(String hexCiphertext) {
        return sm2Decrypt(hexCiphertext, DEFAULT_CHARSET);
    }
}
